#pragma once

#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<vector>
#include<pthread.h>
#include<semaphore.h>

using namespace std;

//条件变量  同步
//互斥量    互斥
//信号量    并发和互斥

template<class T>
class ringqueue
{
public:
    ringqueue(int cap = 5):rq_(cap),cindex_(0),pindex_(0)
    {
        pthread_mutex_init(&procmutex_,nullptr);
        pthread_mutex_init(&consmutex_,nullptr);
        sem_init(&roomsem_,0,rq_.size());
        sem_init(&datasem_,0,0);
    }
    ~ringqueue()
    {
        sem_destroy(&roomsem_);
        sem_destroy(&datasem_);

        pthread_mutex_destroy(&procmutex_);
        pthread_mutex_destroy(&consmutex_);
    }
    void push(const T& in)
    {
        sem_wait(&roomsem_);    //P操作--   申请资源    减空间
        pthread_mutex_lock(&procmutex_);
        rq_[pindex_]=in;
        pindex_++;
        pindex_=pindex_%rq_.size();
        pthread_mutex_unlock(&procmutex_);
        sem_post(&datasem_);    //V操作++   释放资源    加数据
    }
    T pop()
    {
        sem_wait(&datasem_);
        pthread_mutex_lock(&consmutex_);
        T tmp=rq_[cindex_];
        cindex_++;
        cindex_=cindex_%rq_.size();
        pthread_mutex_unlock(&consmutex_);
        sem_post(&roomsem_);    
    }
private:
    vector<T> rq_;              //环形队列
    pthread_mutex_t procmutex_; //生产者锁
    pthread_mutex_t consmutex_; //消费者锁
    sem_t datasem_;             //数据信号量
    sem_t roomsem_;             //空间信号量
    uint32_t cindex_;           //消费者下标
    uint32_t pindex_;           //生产者下标

};